﻿using System;
using Firefly.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Firefly.Framework.Components.Sky
{
    public class Dome
    {
        private int _domeSize;
        private int _domeVertexSize;
        private int _domeIndexSize;
        private VertexPositionTexture[] _domeVertexBuffer;
        private short[] _domeIndexBuffer;

        public Dome(int domeSize)
        {
            _domeSize = domeSize;
            GenerateDome();
        }

        public void DrawUserIndexPrimitives()
        {
            GraphicsService.Instance.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, _domeVertexBuffer, 0, _domeVertexSize, _domeIndexBuffer, 0, _domeIndexSize);
        }

        private void GenerateDome()
        {
            int DomeIndex = 0;
            int latitude = _domeSize / 2;
            int longitude = _domeSize;
            _domeVertexSize = longitude * latitude;
            _domeIndexSize = (longitude - 1) * (latitude - 1) * 2;
            _domeVertexSize *= 2;
            _domeIndexSize *= 2;
            _domeVertexBuffer = new VertexPositionTexture[_domeVertexSize];

            for (int i = 0; i < longitude; i++)
            {
                double moveXZ = 100.0f * (i / ((float)longitude - 1.0f)) * MathHelper.Pi / 180.0;

                for (int j = 0; j < latitude; j++)
                {
                    double moveY = MathHelper.Pi * j / (latitude - 1);

                    _domeVertexBuffer[DomeIndex] = new VertexPositionTexture();
                    _domeVertexBuffer[DomeIndex].Position.X = (float)(Math.Sin(moveXZ) * Math.Cos(moveY));
                    _domeVertexBuffer[DomeIndex].Position.Y = (float)Math.Cos(moveXZ);
                    _domeVertexBuffer[DomeIndex].Position.Z = (float)(Math.Sin(moveXZ) * Math.Sin(moveY));
                    _domeVertexBuffer[DomeIndex].Position *= 10.0f;
                    _domeVertexBuffer[DomeIndex].TextureCoordinate.X = (0.5f / (float)longitude) + (i / (float)longitude);
                    _domeVertexBuffer[DomeIndex].TextureCoordinate.Y = (0.5f / (float)latitude) + (j / (float)latitude);
                    DomeIndex++;
                }
            }

            for (int i = 0; i < longitude; i++)
            {
                double moveXZ = 100.0 * (i / (float)(longitude - 1)) * MathHelper.Pi / 180.0;

                for (int j = 0; j < latitude; j++)
                {
                    double moveY = (MathHelper.Pi * 2.0) - (MathHelper.Pi * j / (latitude - 1));

                    _domeVertexBuffer[DomeIndex] = new VertexPositionTexture();
                    _domeVertexBuffer[DomeIndex].Position.X = (float)(Math.Sin(moveXZ) * Math.Cos(moveY));
                    _domeVertexBuffer[DomeIndex].Position.Y = (float)Math.Cos(moveXZ);
                    _domeVertexBuffer[DomeIndex].Position.Z = (float)(Math.Sin(moveXZ) * Math.Sin(moveY));
                    _domeVertexBuffer[DomeIndex].Position *= 10.0f;
                    _domeVertexBuffer[DomeIndex].TextureCoordinate.X = (0.5f / (float)longitude) + (i / (float)longitude);
                    _domeVertexBuffer[DomeIndex].TextureCoordinate.Y = (0.5f / (float)latitude) + (j / (float)latitude);
                    DomeIndex++;
                }
            }

            _domeIndexBuffer = new short[_domeIndexSize * 3];
            int index = 0;

            for (short i = 0; i < longitude - 1; i++)
            {
                for (short j = 0; j < latitude - 1; j++)
                {
                    _domeIndexBuffer[index++] = (short)((i * latitude) + j);
                    _domeIndexBuffer[index++] = (short)(((i + 1) * latitude) + j);
                    _domeIndexBuffer[index++] = (short)(((i + 1) * latitude) + j + 1);
                    _domeIndexBuffer[index++] = (short)(((i + 1) * latitude) + j + 1);
                    _domeIndexBuffer[index++] = (short)((i * latitude) + j + 1);
                    _domeIndexBuffer[index++] = (short)((i * latitude) + j);
                }
            }

            short offset = (short)(latitude * longitude);

            for (short i = 0; i < longitude - 1; i++)
            {
                for (short j = 0; j < latitude - 1; j++)
                {
                    _domeIndexBuffer[index++] = (short)(offset + (i * latitude) + j);
                    _domeIndexBuffer[index++] = (short)(offset + ((i + 1) * latitude) + j + 1);
                    _domeIndexBuffer[index++] = (short)(offset + ((i + 1) * latitude) + j);
                    _domeIndexBuffer[index++] = (short)(offset + (i * latitude) + j + 1);
                    _domeIndexBuffer[index++] = (short)(offset + ((i + 1) * latitude) + j + 1);
                    _domeIndexBuffer[index++] = (short)(offset + (i * latitude) + j);
                }
            }
        }
    }
}
